#pragma once
#include <vector>
#include <functional>
#include <sys/wait.h>
#include "channel.hpp"
#include "task.hpp"
enum
{
    OK = 0,
    USAGEFAIL,
    PIPEERROR,
    FORKERROR
};
using work_t = std::function<void()>;
class processpool
{
public:
    processpool(int processnum, work_t work) : _processnum(processnum), _work(work)
    {
    }
    int InitProcessPool()
    {
        for (int i = 0; i < _processnum; i++)
        {
            // 1.先有管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
                return PIPEERROR;
            // 2.创建进程
            pid_t fd = fork();
            if (fd < 0)
                return FORKERROR;

            if (fd == 0)
            {
                // child
                ::close(pipefd[1]);
                //重定向，默认从0读
                dup2(pipefd[0], 0);
                _work();
                exit(OK);
            }
            else
            {
                // father
                ::close(pipefd[0]);
                _channels.emplace_back(pipefd[1], fd);
            }
        }
        return OK;
    }
    void DispatchTask()
    {
        int who = 0;
        // 2. 派发任务
        int num = 20;
        while (num--)
        {
            // a. 选择一个任务， 整数
            int task = ts.SelectTask();
            // b. 选择一个子进程channel
            channel &curr = _channels[who++];
            who %= _channels.size();

            std::cout << "######################" << std::endl;
            std::cout << "send " << task << " to " << curr.name() << ", 任务还剩: " << num << std::endl;
            std::cout << "######################" << std::endl;

            // c. 派发任务
            curr.send(task);

            sleep(1);
        }
    }
    void CleanProcessPool()
    {
        for (auto &c : _channels)
        {
            c.close();
        }
        for (auto &c : _channels)
        {
            pid_t rid = ::waitpid(c.id(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child " << rid << " wait ... success" << std::endl;
            }
        }
    }
    ~processpool()
    {
    }

private:
    std::vector<channel> _channels;
    int _processnum;
    work_t _work;
};